#include "natiavtrustdialog.h"
#include "csingleteon.h"
#include "common.h"
#include "invokers/invokerfactory.h"
#include "virusfiledetaildefinition.h"

//#include <DFontSizeManager>
//#include <DApplicationHelper>
#include <QListView>
#include <QTimer>

#include <QTime>
#include <QHeaderView>
#include <QDebug>
//#include <DBlurEffectWidget>
//#include <DTitlebar>
#include <QApplication>


#define TABLE_SPACE 5 //表栏两边间距
#define DIALOG_WIDTH 510 //dialog  宽度
#define DIALOG_HEIGHT 500 //dialog  高度
#define TABLEVIEW_WIDTH 490 //tableview  宽度
#define TABLEVIEW_HEIGHT 320 //tableview  高度
#define TABLEVIEW_ROW_HEIGHT 50 //tableview 每列高度

#define TABLE_COL_QFILES 0 //table表 第二列 隔离文件
#define TABLE_COL_TIME 1 //table表 第三列 添加时间
#define TABLE_COL_CHECK_STATUS 2 //table表 第四列 选择状态
#define TABLE_COL_FILE_PATH 3 //table表 第五列 文件路径
#define TABLE_COL_FILE_NAME 4 //table表 第六列 文件名称
#define TABLE_COL_ADD_TIME 5 //table表 第七列 时间

#define TABLE_COL_1_WIDTH 330 //table表 第二列 宽度
#define TABLE_COL_2_WIDTH 160 //table表 第三列 宽度
#define SPINNER_WIDTH 100 //spinner 宽度
#define SPINNER_HEIGHT 100 //spinner 高度
#define PB_DELETE_WIDTH 140 //移除隔离按钮宽度
#define PB_DELETE_HEIGHT 37 //移除隔离按钮高度
#define PAGE_TABLE 0 //表格页面
#define PAGE_SPINNER 1 //加载页面
#define LEFT_MARGINS 0 //左边距
#define TOP_MARGINS 0 //上边距
#define RIGHT_MARGINS 0 //右边距离
#define BUTTOM_MARGINS 0 //下边距离
#define SPACING 5 //布局间隙

#define SET_ACC_NAME(contral, name) SET_ACCESS_NAME(contral, natiavTrustDialog, name)

NatiavTrustDialog::NatiavTrustDialog(AntiVirusWork *work, QWidget *parent)
    : QFrame(parent)
    , m_work(work)
    , m_monitorInterFaceServer(nullptr)
    , m_checkBoxAll(nullptr)
    , m_model(nullptr)
    , m_PbTrust(nullptr)
    , m_tableView(nullptr)
    , m_proLable(nullptr)
    , m_total(0)
    , m_curret(0)
    , m_quit(false)
    , m_loadingFlag(false)
    , m_delegate(new ResultDelegate(this))
{
    // 安全中心 联网管控dbus服务
    m_monitorInterFaceServer = InvokerFactory::GetInstance().CreateInvoker("com.deepin.defender.MonitorNetFlow",
                                                                           "/com/deepin/defender/MonitorNetFlow",
                                                                           "com.deepin.defender.MonitorNetFlow",
                                                                           ConnectType::SYSTEM, this);

    installEventFilter(this);
    this->resize(DIALOG_WIDTH, DIALOG_HEIGHT);
    this->setMinimumSize(QSize(DIALOG_WIDTH, DIALOG_HEIGHT));
    this->setMaximumSize(QSize(DIALOG_WIDTH, DIALOG_HEIGHT));
    //设置为Dialog
    setWindowFlags(Qt::Dialog);
    //设置为阻态
    setWindowModality(Qt::ApplicationModal);
    //背景透明化
//    setAttribute(Qt::WA_TranslucentBackground);
//    //模糊效果
//    DBlurEffectWidget *m_blurEffect = new DBlurEffectWidget(this);
//    SET_ACC_NAME(m_blurEffect, blurEffectWidget);
//    m_blurEffect->setBlendMode(DBlurEffectWidget::BehindWindowBlend);

//    //设置模糊大小
//    m_blurEffect->resize(size());
//    m_blurEffect->lower();
    //全选
    m_checkBoxAll = new QCheckBox(this);
    SET_ACC_NAME(m_checkBoxAll, checkBoxAll);
    //移出信任确认
    m_PbTrust = new QPushButton(this);
    SET_ACC_NAME(m_PbTrust, trustButton);
    m_PbTrust->setDisabled(true);
    m_TrustfileInfo.clear();

    //界面初始化
    initGUI();

    //全选按钮改变信号
    connect(m_checkBoxAll, SIGNAL(stateChanged(int)), this, SLOT(checkAll(int)));
    //移除按钮点击
    connect(m_PbTrust, SIGNAL(clicked()), this, SLOT(deleteTrust()));
    connect(m_delegate, SIGNAL(sendCheckClickSingal()), this, SLOT(checkBoxAllStatus()));
    //点击表头触发排序
    connect(m_tableView->horizontalHeader(), SIGNAL(sectionClicked(int)), this, SLOT(sortByTableHeaderClicked(int)));
}

NatiavTrustDialog::~NatiavTrustDialog()
{
    disconnect(this);

    m_model->clear();
    m_model->deleteLater();
    m_model = nullptr;
}

//布局
void NatiavTrustDialog::initGUI()
{
    //主布局
    QVBoxLayout *mainlayout = new QVBoxLayout(this);
    //边距离
    mainlayout->setContentsMargins(LEFT_MARGINS, TOP_MARGINS, RIGHT_MARGINS, BUTTOM_MARGINS + 10);
    mainlayout->setSpacing(SPACING);
    QHBoxLayout *titleBarLayout = new QHBoxLayout();
    titleBarLayout->setContentsMargins(LEFT_MARGINS, TOP_MARGINS, RIGHT_MARGINS, BUTTOM_MARGINS);
    //关闭按钮
//    DTitlebar *titleBar = new DTitlebar(this);
//    SET_ACC_NAME(titleBar, titleBar);
//    titleBar->setBackgroundTransparent(true);
//    titleBar->setTitle("");
//    titleBar->setMenuVisible(false);
//    titleBarLayout->addWidget(titleBar, 0, Qt::AlignRight | Qt::AlignTop);
//    mainlayout->addLayout(titleBarLayout);
    //标题  信任区
    QLabel *label_title = new QLabel(tr("Exclusions"), this);
    SET_ACC_NAME(label_title, whiteListTitle);
    label_title->setAlignment(Qt::AlignCenter);
    QFont ft = label_title->font();
    ft.setBold(true);
    //标题字体
    label_title->setFont(ft);
//    DFontSizeManager::instance()->bind(label_title, DFontSizeManager::T5);
    mainlayout->addWidget(label_title);

    //tableview
    QWidget *CenterWidget = new QWidget(this);
    SET_ACC_NAME(CenterWidget, centerWidget);
    CenterWidget->setMinimumWidth(TABLEVIEW_WIDTH);
    //中间表格
    CenterWidget->setLayout(initTableWidget());
    mainlayout->addWidget(CenterWidget, 0, Qt::AlignHCenter);
    QHBoxLayout *hlayout = new QHBoxLayout();
    hlayout->setContentsMargins(15, TOP_MARGINS, 15, BUTTOM_MARGINS);
    //全选
    m_checkBoxAll->setText(tr("Select All"));
    hlayout->addWidget(m_checkBoxAll, 0, Qt::AlignLeft);
    hlayout->addStretch(1);
    m_proLable = new QLabel(this);
    SET_ACC_NAME(m_proLable, proLable);
    hlayout->addWidget(m_proLable, 0, Qt::AlignRight);
    mainlayout->addLayout(hlayout);

    // 按钮  移出信任   Remove from Whitelist
    elideBtnText();
    m_PbTrust->setMinimumSize(QSize(PB_DELETE_WIDTH, PB_DELETE_HEIGHT));
    m_PbTrust->setMaximumSize(QSize(PB_DELETE_WIDTH, PB_DELETE_HEIGHT));
    mainlayout->addWidget(m_PbTrust, 0, Qt::AlignBottom | Qt::AlignHCenter);

    m_checkBoxAll->setDisabled(true);
    m_PbTrust->setDisabled(true);
}

//初始化中间tableview布局
QHBoxLayout *NatiavTrustDialog::initTableWidget()
{
    QHBoxLayout *layout = new QHBoxLayout;
    layout->setMargin(0);
    layout->setSpacing(0);

    //行高   列头去掉
    m_tableView = new QTableView(this);
    SET_ACC_NAME(m_tableView, tableView);
    SET_ACC_NAME(m_tableView->viewport(), viewPort);
    m_tableView->verticalHeader()->setDefaultSectionSize(TABLEVIEW_ROW_HEIGHT);
    m_tableView->verticalHeader()->setVisible(false);
    m_tableView->horizontalHeader()->setStretchLastSection(true);
    m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
    //单选
    m_tableView->setSelectionMode(QAbstractItemView::NoSelection);
    //不可以编辑
    m_tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
    //形状
    m_tableView->setFrameShape(QTableView::NoFrame);
    //栅格
    m_tableView->setShowGrid(false);
    //排序
    m_tableView->setSortingEnabled(true);

    // 连接表格与模型
    m_model = new QStandardItemModel(this);
    m_tableView->setModel(m_model);
    m_tableView->setItemDelegate(m_delegate);
    layout->addWidget(m_tableView);

    // 信任文件
    QStandardItem *standaritem1 = new QStandardItem(tr("Whitelist files"));
    standaritem1->setTextAlignment(Qt::AlignLeft);
    //添加时间
    QStandardItem *standaritem2 = new QStandardItem(tr("Time added"));
    standaritem2->setTextAlignment(Qt::AlignLeft);

    m_model->setHorizontalHeaderItem(TABLE_COL_QFILES, standaritem1);
    m_model->setHorizontalHeaderItem(TABLE_COL_TIME, standaritem2);
    //选择状态
    m_model->setHorizontalHeaderItem(TABLE_COL_CHECK_STATUS, new QStandardItem("checkStatus"));
    //路径
    m_model->setHorizontalHeaderItem(TABLE_COL_FILE_PATH, new QStandardItem("filePath"));
    //文件名称
    m_model->setHorizontalHeaderItem(TABLE_COL_FILE_NAME, new QStandardItem("fileName"));
    //添加时间
    m_model->setHorizontalHeaderItem(TABLE_COL_ADD_TIME, new QStandardItem("addtime"));
    //设置每隔宽度
    m_tableView->setColumnWidth(TABLE_COL_QFILES, TABLE_COL_1_WIDTH);
    m_tableView->setColumnWidth(TABLE_COL_TIME, TABLE_COL_2_WIDTH);
    //隐藏列
    m_tableView->setColumnHidden(TABLE_COL_CHECK_STATUS, true);
    m_tableView->setColumnHidden(TABLE_COL_FILE_PATH, true);
    m_tableView->setColumnHidden(TABLE_COL_FILE_NAME, true);
    m_tableView->setColumnHidden(TABLE_COL_ADD_TIME, true);

    m_tableView->horizontalHeader()->setHighlightSections(false);

    //获得数据
    return layout;
}

bool NatiavTrustDialog::eventFilter(QObject *obj, QEvent *event)
{
    if (this == obj) {
        // 如果当前是字体改变的事件
        if (event->type() == QEvent::FontChange) {
            // 刷新按钮字体
            elideBtnText();
        }
    }
    return QWidget::eventFilter(obj, event);
}

// 关闭事件
void NatiavTrustDialog::closeEvent(QCloseEvent *event)
{
    Q_UNUSED(event);
    m_quit = true;
    // 更新信任区域的数量
    emit notifyUpdateTrustSize();
}

// 表头点击排序
void NatiavTrustDialog::sortByTableHeaderClicked(int index)
{
    // 根据不同的点击列  对应的列进行排序
    if (TABLE_COL_QFILES == index) {
        // 第二列排序
        m_tableView->sortByColumn(TABLE_COL_CHECK_STATUS);
    } else {
        // 第三列排序
        m_tableView->sortByColumn(TABLE_COL_ADD_TIME);
    }
}

void NatiavTrustDialog::elideBtnText()
{
    QFontMetrics fontmet(m_PbTrust->font());
    QString removeText = tr("Remove");
    QString elidedStr = fontmet.elidedText(removeText, Qt::TextElideMode::ElideMiddle, PB_DELETE_WIDTH - 10);
    m_PbTrust->setText(elidedStr);
    if (fontmet.width(removeText) > (PB_DELETE_WIDTH - 10)) {
        m_PbTrust->setToolTip(tr("Remove"));
    } else {
        m_PbTrust->setToolTip("");
    }
}

// 判断全选按钮
void NatiavTrustDialog::checkBoxAllStatus()
{
    //总行数
    int count = m_model->rowCount();
    //选中状态的map
    QMap<int, int> rowMap;
    for (int i = 0; i < count; i++) {
        //按钮的状态
        bool isChecked = m_model->data(m_model->index(i, COLUMN_RISKS), ROLE_CHECKED_STATUS).toBool();
        if (!isChecked) {
            rowMap.insert(i, 0);
            m_model->item(i, TABLE_COL_CHECK_STATUS)->setText("0");
        } else {
            rowMap.insert(i, 1); //如果是选中状态移除
            m_model->item(i, TABLE_COL_CHECK_STATUS)->setText("1");
        }
    }
    //打沟的数量
    int tcount = 0;
    //不打沟的数量
    int fcount = 0;
    QMapIterator<int, int> rowMapIterator(rowMap);
    rowMapIterator.toBack();
    while (rowMapIterator.hasPrevious()) {
        int value;
        rowMapIterator.previous();
        value = rowMapIterator.value();
        if (value == 0) {
            fcount++;
        } else if (value == 1) {
            tcount++;
        }
    }

    //根据数量判断  全选状态
    if (tcount == count) {
        m_checkBoxAll->setCheckState(Qt::CheckState::Checked);
    } else if (fcount == count) {
        m_checkBoxAll->setCheckState(Qt::CheckState::Unchecked);
    } else {
        //有一个没有选中  先把全选设为未选择状态   然后吧以前的选中都恢复
        m_checkBoxAll->setCheckState(Qt::CheckState::Unchecked);
        QMap<int, int>::iterator it;
        for (it = rowMap.begin(); it != rowMap.end(); ++it) {
            int row = it.key();
            QModelIndex index = m_model->index(row, COLUMN_RISKS);
            if (0 == it.value()) {
                m_model->setData(index, false, ROLE_CHECKED_STATUS);
            } else {
                m_model->setData(index, true, ROLE_CHECKED_STATUS);
            }
        }
    }
}

void NatiavTrustDialog::appendFileInfo(TrustFileInfo info)
{
    //锁
    DEFENDER_MUTEX_LOCKER(&SMutex::getInstance().m_mutex);
    //当前行
    int row = m_model->rowCount();
    //文件路径
    QString filePath = info.sFilePath;
    QString fileName = info.sFileName;
    QString addtime = info.sAddTime;

    QStandardItem *c0 = new QStandardItem();
    QStandardItem *c1 = new QStandardItem();

    m_model->setItem(row, 0, c0);
    m_model->setItem(row, 1, c1);
    c0->setData(false, ROLE_CHECKED_STATUS);
    c0->setData(fileName, ROLE_VIRUSFILE_PATH);
    c0->setData(filePath, ROLE_VIRUSFILE_NAME);
    c0->setData(this->font(), Qt::FontRole);
    c1->setData(addtime, ROLE_VIRUSFILE_ADDTIME);

    //保留此两列,用于点击表头排序操作
    m_model->setItem(row, TABLE_COL_CHECK_STATUS, new QStandardItem(QString("0")));
    m_model->setItem(row, TABLE_COL_ADD_TIME, new QStandardItem(QString("%1").arg(addtime)));
}

void NatiavTrustDialog::setCurrentProcess(int nCurrent)
{
    m_proLable->setText(QString("%1/%2").arg(nCurrent).arg(m_total));
}

//自适应
void NatiavTrustDialog::resizeEvent(QResizeEvent *event)
{
    Q_UNUSED(event);
    if (m_model->rowCount() == 0) {
        return;
    } else {
        int height = m_tableView->indexWidget(m_model->index(0, 0))->size().height();
        for (int i = 0; i < m_model->rowCount(); i++) {
            m_tableView->setRowHeight(i, height);
        }
    }
}

//全选
void NatiavTrustDialog::checkAll(int status)
{
    int count = m_model->rowCount();
    for (int i = 0; i < count; i++) {
        QModelIndex index = m_model->index(i, COLUMN_RISKS);
        switch (status) {
        case 0:
            m_model->setData(index, false, ROLE_CHECKED_STATUS);
            break;
        case 1:
            break;
        case 2:
            m_model->setData(index, true, ROLE_CHECKED_STATUS);
            break;
        }
    }
}

//删除信任
void NatiavTrustDialog::deleteTrust()
{
    //总行数
    int count = m_model->rowCount();
    QStringList needRemovePathList;
    //选中状态的map
    QMap<int, int> rowMap;
    for (int i = 0; i < count; i++) {
        //按钮的状态
        bool isChecked = m_model->data(m_model->index(i, COLUMN_RISKS), ROLE_CHECKED_STATUS).toBool();
        if (!isChecked) {
            rowMap.insert(i, 0);
        } else {
            //true是选中状态  要移除
            rowMap.insert(i, 1);
            //文件路径
            QString filepath = m_model->data(m_model->index(i, COLUMN_RISKS), ROLE_VIRUSFILE_NAME).toString();
            needRemovePathList.append(filepath);
        }
    }

    // 如果正在扫描时，则不隔离u盘病毒，并系统弹窗提示
    if (needRemovePathList.size() && ScanStatus::Free != m_work->getCurrentScanStatus()) {
        m_work->showNormalNotification(tr("Scanning virus, please try later"));
        return;
    }

    // 移除隔离文件
    for (const QString &path : needRemovePathList) {
        //发送  删除隔离文件信号
        Q_EMIT requsetRemoveTrustFile(path);
    }

    // 添加安全日志
    DBUS_NOBLOCK_INVOKE(m_monitorInterFaceServer,
                        "AddSecurityLog",
                        SECURITY_LOG_TYPE_ANTIAV,
                        tr("Removed from whitelist: %1").arg(needRemovePathList.size()));

    //遍历选中状态的map
    QMapIterator<int, int> rowMapIterator(rowMap);
    rowMapIterator.toBack();
    //是否是最后一个
    while (rowMapIterator.hasPrevious()) {
        rowMapIterator.previous();
        int key = rowMapIterator.key();
        int value = rowMapIterator.value();
        //如果是选中状态
        if (1 == value) {
            //缓存删除
            m_model->removeRow(key);
            m_TrustfileInfo.removeAt(key);
        }
    }

    // 删除完后剩余的总行数
    int count1 = m_model->rowCount();
    m_total = count1;
    setCurrentProcess(count1);
    if (count1 == 0) {
        // 如果没有数据了 全选不会勾选 并且至于灰色
        m_checkBoxAll->setCheckState(Qt::CheckState::Unchecked);
        m_checkBoxAll->setDisabled(true);
    }
}

//table 单选对象
void NatiavTrustDialog::tableCheckItem()
{
    checkBoxAllStatus();
}

//信任文件接受
void NatiavTrustDialog::receptionTrustFile(QList<TrustFileInfo> sInfos)
{
    //为了避免多次加载　当加载一次以后,就不会再有加载动作
    if (m_loadingFlag) {
        return;
    };
    m_loadingFlag = true;
    //展现信任列表
    m_TrustfileInfo = sInfos;
    m_total = m_TrustfileInfo.size();
    for (int i = 0; i < m_total; i++) {
        // 如果加载中退出 就不在进行加载
        if (m_quit)
            return;
        appendFileInfo(m_TrustfileInfo.at(i));
        setCurrentProcess(i + 1);
        QApplication::processEvents();
    }
    // 全选状态和按钮状态设定
    m_PbTrust->setDisabled(false);
    m_checkBoxAll->setCheckState(Qt::CheckState::Unchecked);
    if (m_total == 0) {
        // 没有隔离数据为不可以操作
        m_checkBoxAll->setDisabled(true);
    } else {
        // 有数据可以操作
        m_checkBoxAll->setDisabled(false);
    }
}
